package com.AdvancedDemos.单元测试_反射_注解.反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

public class _2_反射构造函数 {/*成员方法,变量,构造函数反射中,构造函数反射使用最多*/

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        Class clazz = Class.forName("com.AdvancedDemos.单元测试_反射_注解.反射.Person");//获取字节码文件对象
        System.out.println(clazz);//class com.AdvancedDemos.单元测试_反射_注解_代理.反射.Person

        /**Class提供了从类中获取构造器的方法
         * Constructor<?>[] getConstructors () --- 获取全部构造器（只能获取public修饰的)
         * Constructor<?>[] getDeclaredConstructors() --- 获取全部构造器（只要存在就能拿到)
         * Constructor<T> getConstructor (class<?>... parameterTypes) --- 获取某个构造器（只能获取public修饰的）
         * Constructor<T> getDeclaredConstructor （class<?>... parameterTypes) --- 获取某个构造器（只要存在就能拿到)
         */
        System.out.println("------------------------");
        Constructor[] constructors = clazz.getConstructors();//获取public构造
        System.out.println(Arrays.toString(constructors));//[public com.AdvancedDemos.单元测试_反射_注解_代理.反射.Person()]
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();//获取全部声明的构造
        System.out.println(Arrays.toString(declaredConstructors));//[com.AdvancedDemos.单元测试_反射_注解_代理.反射.Person(java.lang.String,int,java.lang.String), private com.AdvancedDemos.单元测试_反射_注解_代理.反射.Person(java.lang.String), public com.AdvancedDemos.单元测试_反射_注解_代理.反射.Person()]


        System.out.println("------------------------");
        /**Constructor提供的方法
         * T newInstance (object. . . initargs) --- 调用此构造器对象表示的构造器，并传入参数，完成对象的初始化并返回
         * public void setAccessible(boolean flag) --- 设置为true，表示禁止检查访问控制（暴力反射）
         */
        Constructor constructor = clazz.getConstructor(null/*或者不写*/);//获取空参构造
        Object o = constructor.newInstance();//使用构造
        Person person = (Person) o;
        System.out.println(o.toString());//Person{name='null', age=0, sex='null'}
        System.out.println(person.toString());//Person{name='null', age=0, sex='null'}


        System.out.println("------------------------");
        Constructor constructor1 = clazz.getDeclaredConstructor(String.class);//获取声明的单参构造
        System.out.println(constructor1);//private com.AdvancedDemos.单元测试_反射_注解_代理.反射.Person(java.lang.String)
        // 可以获得private构造,但是类外无法直接使用private构造,需要强制获取访问权限
        /* 没有访问权限,需要强制获取
        class com.AdvancedDemos.单元测试_反射_注解_代理.反射._2_反射构造函数 cannot access a member of class com.AdvancedDemos.单元测试_反射_注解_代理.反射.Person with modifiers "private"
         */
        constructor1.setAccessible(true);//设置为true，表示禁止检查访问控制（暴力反射）

        Person person1 = (Person) constructor1.newInstance("hello");
        System.out.println(person1);//Person{name='hello', age=0, sex='null'}


        System.out.println("------------------------");
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class, String.class);//获取三参构造,参数是Person中三参构造的形参类型
        Object o1 = declaredConstructor.newInstance("张三", 1, "女");
        System.out.println(o1);//Person{name='张三', age=1, sex='女'}

    }
}

